﻿#define VTKM_NO_ERROR_ON_MIXED_CUDA_CXX_TAG

#include "EulerEquation.h"
#include "Application.h"
#include "Mesh.h"
#include "Transient.h"

#include "worklet/ComputeResidual.h"
#include <vtkm/cont/Algorithm.h>

EulerEquation::EulerEquation(const Configuration& cfg)
  : System(cfg)
  , _eq(Get<Real>("mach"))
{
  _bnd_type_id["FarField"] = 2;
  _bnd_type_id["Wall"] = 3;
}

void EulerEquation::Init()
{
  System::Init();
  _data_set.SetCellSet(_mesh.GetCellSet());
  _data_set.AddCoordinateSystem(_mesh.GetCoordinate());

  // 通过初始条件的赋值变量
  this->AddCellVariable<Real>("density");
  this->AddCellVariable<Vec3f>("momentum");
  this->AddCellVariable<Real>("rhoe");

  // 对 solution 赋值
  this->InitialCondition();

  // 写回DataSet，用来输出DataSet
  Loops::SolutionToArray(*this);
  _rhs.Allocate(_solution.GetNumberOfValues());

  Info("EulerEquation::Init");
}

void EulerEquation::Evolve()
{
  _timer.Reset();

  PreSolve();
  Solve();
  PostSolve();

  Info("EulerianSystem::Evolve运行完成，", "时间: ", _timer.GetElapsedTime(), " s");
}

void EulerEquation::PreSolve() {}


void EulerEquation::TimeIntegration()
{
  Loops::ExplictFirtOrder(*this);

  auto result = vtkm::cont::Algorithm::Reduce(_rhs, vtkm::TypeTraits<VType>::ZeroInitialization());
  std::cout << "Res: " << result[1] / _rhs.GetNumberOfValues() << std::endl;

    //std::cout << "i=100: " << _rhs.ReadPortal().Get(100) << std::endl;
}

void EulerEquation::Solve()
{
  UpdateResidual();
  TimeIntegration();
}

void EulerEquation::PostSolve()
{
  Loops::SolutionToArray(*this);
}

ArrayHandle<typename EulerEquation::VType>& EulerEquation::GetSolution()
{
  return _solution;
}

ArrayHandle<typename EulerEquation::VType>& EulerEquation::GetRhs()
{
  return _rhs;
}

#undef VTKM_NO_ERROR_ON_MIXED_CUDA_CXX_TAG
